package com.vainycos.lotterysearch.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vainycos.lotterysearch.enums.ExceptionEnum;
import com.vainycos.lotterysearch.exception.BusinessException;
import com.vainycos.lotterysearch.mapper.DoubleColorBallMapper;
import com.vainycos.lotterysearch.model.DoubleColorBall;
import com.vainycos.lotterysearch.model.ro.DoubleColorRo;
import com.vainycos.lotterysearch.service.notify.DingNotify;
import com.vainycos.lotterysearch.service.notify.MailNotify;
import com.vainycos.lotterysearch.tool.GetLottery;
import com.vainycos.lotterysearch.utils.DingTalkPushUtil;
import com.vainycos.lotterysearch.utils.FreeApiUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;

/**
 * @author: Vainycos
 * @description 双色球服务
 * @date: 2022/11/4 14:13
 */
@Slf4j
@Service
public class DoubleColorService extends ServiceImpl<DoubleColorBallMapper, DoubleColorBall> {

    @Resource
    private DoubleColorBallMapper doubleColorBallMapper;

    @Lazy
    @Autowired
    private MailNotify mailNotify;

    @Lazy
    @Autowired
    private DingNotify dingNotify;

    @Value("${receive.mail-address:}")
    private String receiveMailAddress;

    /**
     * 全量新增开奖信息
     * @return
     */
    public boolean batchInsertInit (){
        // 判断如果数据库有数据则提示需清空之后再全量同步
        DoubleColorBall doubleColorBall = doubleColorBallMapper.selectOne(new LambdaQueryWrapper<DoubleColorBall>().last("limit 1"));
        if (doubleColorBall != null){
            throw new BusinessException(ExceptionEnum.BATCH_INIT);
        }
        List<DoubleColorBall> allDCB = GetLottery.getAllDCB();
        log.info("扫描到双色球开奖信息总共{}条, 开始全量更新...", allDCB.size());
        return this.saveBatch(allDCB);
    }

    /**
     * 增量同步
     * @return
     */
    public boolean syncInsert(){
        // 获取最近一期
        DoubleColorBall doubleColorBall = searchLatestDoubleColor();
        if (doubleColorBall == null){
            // 数据库尚未初始化数据，进行全量更新
            log.info("双色球尚未初始化数据，进行全量更新...");
            return batchInsertInit();
        }
        // 获取最近期号之后的开奖情况
        List<DoubleColorBall> laterDoubleColor = GetLottery.getLaterDCB(doubleColorBall.getPeriodId());
        if (laterDoubleColor.size() == 0){
            throw new BusinessException(ExceptionEnum.SYNC_INSERT);
        }
        log.info("获取到双色球增量开奖信息{}条, 开始增量同步...", laterDoubleColor.size());
        boolean saveBatch = this.saveBatch(laterDoubleColor);
        log.info("增量同步成功!");
        // 通知
        mailNotify.mailNotifyDoubleColorBall(laterDoubleColor, Arrays.asList(receiveMailAddress));
        dingNotify.notifyDoubleColorBall(laterDoubleColor);
        return saveBatch;
    }

    /**
     * 查询最近一期开奖情况
     * @return
     */
    public DoubleColorBall searchLatestDoubleColor(){
        // 获取最近的一条记录
        LambdaQueryWrapper<DoubleColorBall> query = new LambdaQueryWrapper<>();
        query.orderByDesc(DoubleColorBall::getPeriodId);
        query.last("limit 1");
        return doubleColorBallMapper.selectOne(query);
    }

    /**
     * 根据期数查询单期开奖情况
     * @param periodId
     * @return
     */
    public DoubleColorBall getDCBBySinglePeriodId(int periodId){
        LambdaQueryWrapper<DoubleColorBall> query = new LambdaQueryWrapper<>();
        query.eq(DoubleColorBall::getPeriodId, periodId);
        return doubleColorBallMapper.selectOne(query);
    }

    /**
     * 获取该期之后的开奖情况
     * @param periodId
     * @return
     */
    public List<DoubleColorBall> getLaterBLB(int periodId){
        LambdaQueryWrapper<DoubleColorBall> query = new LambdaQueryWrapper<>();
        query.gt(DoubleColorBall::getPeriodId, periodId);
        query.orderByAsc(DoubleColorBall::getPeriodId);
        return doubleColorBallMapper.selectList(query);
    }

    /**
     * 前区号码历史中奖率， 前区号码匹配量/历史开奖量
     * @param frontAreaNum
     * @return
     */
    public String historyFrontArea(int frontAreaNum){
        return doubleColorBallMapper.historyFrontArea(frontAreaNum);
    }

    /**
     * 后区号码历史中奖率， 前区号码匹配量/历史开奖量
     * @param endAreaNum
     * @return
     */
    public String historyEndArea(int endAreaNum){
        return doubleColorBallMapper.historyEndArea(endAreaNum);
    }

    /**
     * 中奖规则：
     * 6红+1蓝 一等奖
     * 6红+0蓝 二等奖
     * 5红+1蓝 三等奖
     * 5红+0蓝 / 4红+1蓝 四等奖
     * 4红+0蓝 / 3红+1蓝 五等奖
     * 2红+1蓝 / 1红+1蓝 / 0红+1蓝 六等奖
     *
     * @param doubleColorRo   输入号码
     * @param doubleColorBall 开奖号码
     * @return
     */
    public int matchLevelPrizes(DoubleColorRo doubleColorRo, DoubleColorBall doubleColorBall) {
        List<Integer> redBullList = Arrays.asList(doubleColorBall.getRedBallOne(),
                doubleColorBall.getRedBallTwo(),
                doubleColorBall.getRedBallThree(),
                doubleColorBall.getRedBallFour(),
                doubleColorBall.getRedBallFive(),
                doubleColorBall.getRedBallSix()
        );

        // 红球中奖计数
        int redBallCount = 0;
        // 蓝球中奖计数
        int blueBallCount = 0;

        redBallCount += redBullList.contains(doubleColorRo.getRedBallOne()) ? 1 : 0;
        redBallCount += redBullList.contains(doubleColorRo.getRedBallTwo()) ? 1 : 0;
        redBallCount += redBullList.contains(doubleColorRo.getRedBallThree()) ? 1 : 0;
        redBallCount += redBullList.contains(doubleColorRo.getRedBallFour()) ? 1 : 0;
        redBallCount += redBullList.contains(doubleColorRo.getRedBallFive()) ? 1 : 0;
        redBallCount += redBullList.contains(doubleColorRo.getRedBallSix()) ? 1 : 0;

        blueBallCount += (doubleColorRo.getBlueBallOne() == doubleColorBall.getBlueBallOne()) ? 1 : 0;

        boolean level6 = (redBallCount == 2 && blueBallCount == 1) || (redBallCount == 1 && blueBallCount == 1) || (redBallCount == 0 && blueBallCount ==1);
        boolean level5 = (redBallCount == 4 && blueBallCount == 0) || (redBallCount == 3 && blueBallCount == 1);
        boolean level4 = (redBallCount == 5 && blueBallCount == 0) || (redBallCount == 4 && blueBallCount == 1);
        boolean level3 = (redBallCount == 5 && blueBallCount == 1);
        boolean level2 = (redBallCount == 6 && blueBallCount == 0);
        boolean level1 = (redBallCount == 6 && blueBallCount == 1);

        if (level6){
            return 6;
        }else if (level5){
            return 5;
        }else if (level4){
            return 4;
        }else if (level3){
            return 3;
        }else if (level2){
            return 2;
        }else if (level1){
            return 1;
        }else {
            return 0;
        }
    }

    /**
     * 根据中奖情况输出兑奖描述
     * @param resultDoubleColorBall 开奖情况
     * @param doubleColorRo 用户号码
     * @return
     */
    public String describeByPrice(DoubleColorBall resultDoubleColorBall, DoubleColorRo doubleColorRo){
        StringBuffer result = new StringBuffer();
        result.append("期号：" + resultDoubleColorBall.getPeriodId() + "。"
                + "开奖日期：" + resultDoubleColorBall.getLotteryDate() + "。"
                + "开奖号码：" + resultDoubleColorBall.winnerResult() + "。"
                + "您的号码：" + doubleColorRo.inputNumberResult() + "。");
        int i = matchLevelPrizes(doubleColorRo, resultDoubleColorBall);
        if (i > 0){
            result.append("恭喜您中奖了，中了" + i + "等奖");
        }else {
            result.append("不好意思您未中奖，希望下次好运");
        }

        return result.toString();
    }

    /**
     * 仅输出开奖情况
     * @param resultDoubleColorBall 开奖情况
     * @return
     */
    public String describe(DoubleColorBall resultDoubleColorBall){
        StringBuffer result = new StringBuffer();
        result.append("期号：" + resultDoubleColorBall.getPeriodId() + "。"
                + "开奖日期：" + resultDoubleColorBall.getLotteryDate() + "。"
                + "开奖号码：" + resultDoubleColorBall.winnerResult() + "。");
        return result.toString();
    }

    /**
     * 仅输出开奖情况 提供markdown内容输出
     * @param resultDoubleColorBall 开奖情况
     * @return
     */
    public String describeForMarkdown(String subject, DoubleColorBall resultDoubleColorBall){
        String result =
//                "> " + FreeApiUtil.dailyWord() + " \n" +
                "## [幸运小助手]提醒您：" + subject + " \n" +
                "开奖号码：" + resultDoubleColorBall.winnerResult() + " \n" +
                "![counting-money-in-the-dark](https://gitee.com/dearvainycos/my-pic/raw/master/img/counting-money-in-the-dark.jpg)";
        return result;
    }
}
